/*
board-games:	An educational framework for board games programming.
    Copyright (C) 2008  Daniel Gutson, FuDePAN
    
    This file is part of board-games.

    board-games is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    board-games is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
*/

#include <stddef.h>
#include "common_sdk/board.h"

/* Referee API: from referee to framework */

enum _ALL_PLAYERS
{
    ALL_PLAYERS
};

enum _NEVER_TIMEOUT
{
    NEVER
};

typedef size_t PlayerID;

class SharedBoard;

struct PlayersProxy
{    
    virtual size_t number_of_players() const = 0;
    virtual void send_message(PlayerID playerID, const void* msgdata, size_t size) throw(PlayerID) = 0;
    virtual void receive_message(PlayerID playerID, void*& response, size_t& response_size) throw(PlayerID) = 0;
    virtual bool player_running(PlayerID playerID) const = 0;
    virtual void set_player_timeout(PlayerID playerID, size_t milliseconds) = 0;
    virtual void set_player_timeout(PlayerID playerID, _NEVER_TIMEOUT) = 0;
    virtual void send_board(PlayerID playerID, SharedBoard& board) = 0;
//    virtual Board* allocate_board(size_t rows, size_t cols, size_t cell_size) = 0;

    // the ALL_PLAYERS version:
    virtual bool player_running(_ALL_PLAYERS) const = 0;
    virtual void set_player_timeout(_ALL_PLAYERS, size_t milliseconds) = 0;
    virtual void set_player_timeout(_ALL_PLAYERS, _NEVER_TIMEOUT) = 0;
    virtual void send_board(_ALL_PLAYERS, SharedBoard& board) = 0;

    template <class T>
    void receive_message(PlayerID playerID, T& t) throw(PlayerID, const char*)
    {
        void* received_data;
        size_t received_size;
        receive_message(playerID, received_data, received_size);
        if (received_size == sizeof(T))
            t = *reinterpret_cast<T*>(received_data);
        else
            throw "Invalid message";
    }
    
    template <class T>
    void send_message(PlayerID playerID, const T& t) throw(PlayerID)
    {
        send_message(playerID, &t, sizeof(T));
    }
    
    
protected:
    virtual ~PlayersProxy(){}
};

class Referee
{
public:
    
    typedef PlayerID Winner;
    
    virtual bool accepts_number_of_players(size_t players) = 0;
    
    virtual Winner do_match() throw(PlayerID, const char*) = 0;
    
    virtual ~Referee(){}
};

extern "C" {
extern Referee* initialize(PlayersProxy* playersProxy);
}
